import Axios, { AxiosInstance } from "axios";
import {
  IList,
  IListCreation,
  IProject,
  ISpace,
  ITask,
  ITaskCreation,
  ITeam,
  IUser,
  IComment
} from "./ClickUpInterfaces";
import config from "./config";

/**
 * As the API is still a WIP this will use some hacks there and there
 * The biggest one is the use of both the user public api key (official api) and a bearer token (non-official api)
 */
export class ClickUp {
  private bearer: string;
  private publicKey: string;
  private hackAxios: AxiosInstance;
  private officialAxios: AxiosInstance;

  constructor(publicKey: string, bearerToken: string) {
    this.bearer = bearerToken;
    this.publicKey = publicKey;

    this.hackAxios = Axios.create({
      baseURL: config.clickUpConfig.domain,
      timeout: 30000,
      headers: { Authorization: "Bearer " + this.bearer }
    });

    this.officialAxios = Axios.create({
      baseURL: config.clickUpConfig.officialApiDomain,
      timeout: 30000,
      headers: { Authorization: this.publicKey }
    });
  }

  public async getTeams(): Promise<ITeam[]> {
    return (await this.officialAxios.get("/team")).data.teams;
  }

  public async getTeamUsers(teamId: string): Promise<IUser[]> {
    return (await this.hackAxios.get("/team/" + teamId)).data.members.map(
      m => m.user
    );
  }

  public async getTeamSpaces(teamId: string): Promise<ISpace[]> {
    return (await this.officialAxios.get("/team/" + teamId + "/space")).data
      .spaces;
  }

  public async getSpaceProjects(spaceId: string): Promise<IProject[]> {
    return (await this.officialAxios.get("/space/" + spaceId + "/project")).data
      .projects;
  }

  public async getListTasks(listId: string, teamId: string) {
    return (await this.officialAxios.get("/team/" + teamId + "/task", {
      params: {
        list_ids: [listId],
        subtasks: true
      }
    })).data.tasks;
  }

  public async createTask(
    newTask: ITaskCreation,
    listId: string
  ): Promise<ITask> {
    return (await this.hackAxios.post<ITask>(
      "/subcategory/" + listId + "/task",
      newTask
    )).data;
  }

  public async commentTask(
    taskId: string,
    comment: IComment
  ): Promise<{ id: string }> {
    return (await this.hackAxios.post<{ id: string }>(
      "/task/" + taskId + "/comment",
      comment
    )).data;
  }

  public async createList(
    newList: IListCreation,
    projectId: string
  ): Promise<IList> {
    return (await this.officialAxios.post<IList>(
      "/project/" + projectId + "/list",
      newList
    )).data;
  }
}
